module.exports = function convert_cyr_string (str, from, to) { // eslint-disable-line camelcase
  //  discuss at: https://locutus.io/php/convert_cyr_string/
  // original by: Brett Zamir (https://brett-zamir.me)
  //      note 1: Assumes and converts to Unicode strings with character
  //      note 1: code equivalents of the same numbers as in the from or
  //      note 1: target character set; Note that neither the input or output
  //      note 1: should be treated as actual Unicode, since the PHP function
  //      note 1: this is original by does not either
  //      note 1: One could easily represent (or convert the results) of a
  //      note 1: string form as arrays of code points instead but since JavaScript
  //      note 1: currently has no clear binary data type, we chose to use strings
  //      note 1: as in PHP
  //   example 1: convert_cyr_string(String.fromCharCode(214), 'k', 'w').charCodeAt(0) === 230; // Char. 214 of KOI8-R gives equivalent number value 230 in win1251
  //   returns 1: true

  const _cyrWin1251 = [
    0,
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20,
    21,
    22,
    23,
    24,
    25,
    26,
    27,
    28,
    29,
    30,
    31,
    32,
    33,
    34,
    35,
    36,
    37,
    38,
    39,
    40,
    41,
    42,
    43,
    44,
    45,
    46,
    47,
    48,
    49,
    50,
    51,
    52,
    53,
    54,
    55,
    56,
    57,
    58,
    59,
    60,
    61,
    62,
    63,
    64,
    65,
    66,
    67,
    68,
    69,
    70,
    71,
    72,
    73,
    74,
    75,
    76,
    77,
    78,
    79,
    80,
    81,
    82,
    83,
    84,
    85,
    86,
    87,
    88,
    89,
    90,
    91,
    92,
    93,
    94,
    95,
    96,
    97,
    98,
    99,
    100,
    101,
    102,
    103,
    104,
    105,
    106,
    107,
    108,
    109,
    110,
    111,
    112,
    113,
    114,
    115,
    116,
    117,
    118,
    119,
    120,
    121,
    122,
    123,
    124,
    125,
    126,
    127,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    46,
    154,
    174,
    190,
    46,
    159,
    189,
    46,
    46,
    179,
    191,
    180,
    157,
    46,
    46,
    156,
    183,
    46,
    46,
    182,
    166,
    173,
    46,
    46,
    158,
    163,
    152,
    164,
    155,
    46,
    46,
    46,
    167,
    225,
    226,
    247,
    231,
    228,
    229,
    246,
    250,
    233,
    234,
    235,
    236,
    237,
    238,
    239,
    240,
    242,
    243,
    244,
    245,
    230,
    232,
    227,
    254,
    251,
    253,
    255,
    249,
    248,
    252,
    224,
    241,
    193,
    194,
    215,
    199,
    196,
    197,
    214,
    218,
    201,
    202,
    203,
    204,
    205,
    206,
    207,
    208,
    210,
    211,
    212,
    213,
    198,
    200,
    195,
    222,
    219,
    221,
    223,
    217,
    216,
    220,
    192,
    209,
    0,
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20,
    21,
    22,
    23,
    24,
    25,
    26,
    27,
    28,
    29,
    30,
    31,
    32,
    33,
    34,
    35,
    36,
    37,
    38,
    39,
    40,
    41,
    42,
    43,
    44,
    45,
    46,
    47,
    48,
    49,
    50,
    51,
    52,
    53,
    54,
    55,
    56,
    57,
    58,
    59,
    60,
    61,
    62,
    63,
    64,
    65,
    66,
    67,
    68,
    69,
    70,
    71,
    72,
    73,
    74,
    75,
    76,
    77,
    78,
    79,
    80,
    81,
    82,
    83,
    84,
    85,
    86,
    87,
    88,
    89,
    90,
    91,
    92,
    93,
    94,
    95,
    96,
    97,
    98,
    99,
    100,
    101,
    102,
    103,
    104,
    105,
    106,
    107,
    108,
    109,
    110,
    111,
    112,
    113,
    114,
    115,
    116,
    117,
    118,
    119,
    120,
    121,
    122,
    123,
    124,
    125,
    126,
    127,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    184,
    186,
    32,
    179,
    191,
    32,
    32,
    32,
    32,
    32,
    180,
    162,
    32,
    32,
    32,
    32,
    168,
    170,
    32,
    178,
    175,
    32,
    32,
    32,
    32,
    32,
    165,
    161,
    169,
    254,
    224,
    225,
    246,
    228,
    229,
    244,
    227,
    245,
    232,
    233,
    234,
    235,
    236,
    237,
    238,
    239,
    255,
    240,
    241,
    242,
    243,
    230,
    226,
    252,
    251,
    231,
    248,
    253,
    249,
    247,
    250,
    222,
    192,
    193,
    214,
    196,
    197,
    212,
    195,
    213,
    200,
    201,
    202,
    203,
    204,
    205,
    206,
    207,
    223,
    208,
    209,
    210,
    211,
    198,
    194,
    220,
    219,
    199,
    216,
    221,
    217,
    215,
    218
  ]
  const _cyrCp866 = [
    0,
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20,
    21,
    22,
    23,
    24,
    25,
    26,
    27,
    28,
    29,
    30,
    31,
    32,
    33,
    34,
    35,
    36,
    37,
    38,
    39,
    40,
    41,
    42,
    43,
    44,
    45,
    46,
    47,
    48,
    49,
    50,
    51,
    52,
    53,
    54,
    55,
    56,
    57,
    58,
    59,
    60,
    61,
    62,
    63,
    64,
    65,
    66,
    67,
    68,
    69,
    70,
    71,
    72,
    73,
    74,
    75,
    76,
    77,
    78,
    79,
    80,
    81,
    82,
    83,
    84,
    85,
    86,
    87,
    88,
    89,
    90,
    91,
    92,
    93,
    94,
    95,
    96,
    97,
    98,
    99,
    100,
    101,
    102,
    103,
    104,
    105,
    106,
    107,
    108,
    109,
    110,
    111,
    112,
    113,
    114,
    115,
    116,
    117,
    118,
    119,
    120,
    121,
    122,
    123,
    124,
    125,
    126,
    127,
    225,
    226,
    247,
    231,
    228,
    229,
    246,
    250,
    233,
    234,
    235,
    236,
    237,
    238,
    239,
    240,
    242,
    243,
    244,
    245,
    230,
    232,
    227,
    254,
    251,
    253,
    255,
    249,
    248,
    252,
    224,
    241,
    193,
    194,
    215,
    199,
    196,
    197,
    214,
    218,
    201,
    202,
    203,
    204,
    205,
    206,
    207,
    208,
    35,
    35,
    35,
    124,
    124,
    124,
    124,
    43,
    43,
    124,
    124,
    43,
    43,
    43,
    43,
    43,
    43,
    45,
    45,
    124,
    45,
    43,
    124,
    124,
    43,
    43,
    45,
    45,
    124,
    45,
    43,
    45,
    45,
    45,
    45,
    43,
    43,
    43,
    43,
    43,
    43,
    43,
    43,
    35,
    35,
    124,
    124,
    35,
    210,
    211,
    212,
    213,
    198,
    200,
    195,
    222,
    219,
    221,
    223,
    217,
    216,
    220,
    192,
    209,
    179,
    163,
    180,
    164,
    183,
    167,
    190,
    174,
    32,
    149,
    158,
    32,
    152,
    159,
    148,
    154,
    0,
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20,
    21,
    22,
    23,
    24,
    25,
    26,
    27,
    28,
    29,
    30,
    31,
    32,
    33,
    34,
    35,
    36,
    37,
    38,
    39,
    40,
    41,
    42,
    43,
    44,
    45,
    46,
    47,
    48,
    49,
    50,
    51,
    52,
    53,
    54,
    55,
    56,
    57,
    58,
    59,
    60,
    61,
    62,
    63,
    64,
    65,
    66,
    67,
    68,
    69,
    70,
    71,
    72,
    73,
    74,
    75,
    76,
    77,
    78,
    79,
    80,
    81,
    82,
    83,
    84,
    85,
    86,
    87,
    88,
    89,
    90,
    91,
    92,
    93,
    94,
    95,
    96,
    97,
    98,
    99,
    100,
    101,
    102,
    103,
    104,
    105,
    106,
    107,
    108,
    109,
    110,
    111,
    112,
    113,
    114,
    115,
    116,
    117,
    118,
    119,
    120,
    121,
    122,
    123,
    124,
    125,
    126,
    127,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    205,
    186,
    213,
    241,
    243,
    201,
    32,
    245,
    187,
    212,
    211,
    200,
    190,
    32,
    247,
    198,
    199,
    204,
    181,
    240,
    242,
    185,
    32,
    244,
    203,
    207,
    208,
    202,
    216,
    32,
    246,
    32,
    238,
    160,
    161,
    230,
    164,
    165,
    228,
    163,
    229,
    168,
    169,
    170,
    171,
    172,
    173,
    174,
    175,
    239,
    224,
    225,
    226,
    227,
    166,
    162,
    236,
    235,
    167,
    232,
    237,
    233,
    231,
    234,
    158,
    128,
    129,
    150,
    132,
    133,
    148,
    131,
    149,
    136,
    137,
    138,
    139,
    140,
    141,
    142,
    143,
    159,
    144,
    145,
    146,
    147,
    134,
    130,
    156,
    155,
    135,
    152,
    157,
    153,
    151,
    154
  ]
  const _cyrIso88595 = [
    0,
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20,
    21,
    22,
    23,
    24,
    25,
    26,
    27,
    28,
    29,
    30,
    31,
    32,
    33,
    34,
    35,
    36,
    37,
    38,
    39,
    40,
    41,
    42,
    43,
    44,
    45,
    46,
    47,
    48,
    49,
    50,
    51,
    52,
    53,
    54,
    55,
    56,
    57,
    58,
    59,
    60,
    61,
    62,
    63,
    64,
    65,
    66,
    67,
    68,
    69,
    70,
    71,
    72,
    73,
    74,
    75,
    76,
    77,
    78,
    79,
    80,
    81,
    82,
    83,
    84,
    85,
    86,
    87,
    88,
    89,
    90,
    91,
    92,
    93,
    94,
    95,
    96,
    97,
    98,
    99,
    100,
    101,
    102,
    103,
    104,
    105,
    106,
    107,
    108,
    109,
    110,
    111,
    112,
    113,
    114,
    115,
    116,
    117,
    118,
    119,
    120,
    121,
    122,
    123,
    124,
    125,
    126,
    127,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    179,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    225,
    226,
    247,
    231,
    228,
    229,
    246,
    250,
    233,
    234,
    235,
    236,
    237,
    238,
    239,
    240,
    242,
    243,
    244,
    245,
    230,
    232,
    227,
    254,
    251,
    253,
    255,
    249,
    248,
    252,
    224,
    241,
    193,
    194,
    215,
    199,
    196,
    197,
    214,
    218,
    201,
    202,
    203,
    204,
    205,
    206,
    207,
    208,
    210,
    211,
    212,
    213,
    198,
    200,
    195,
    222,
    219,
    221,
    223,
    217,
    216,
    220,
    192,
    209,
    32,
    163,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    0,
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20,
    21,
    22,
    23,
    24,
    25,
    26,
    27,
    28,
    29,
    30,
    31,
    32,
    33,
    34,
    35,
    36,
    37,
    38,
    39,
    40,
    41,
    42,
    43,
    44,
    45,
    46,
    47,
    48,
    49,
    50,
    51,
    52,
    53,
    54,
    55,
    56,
    57,
    58,
    59,
    60,
    61,
    62,
    63,
    64,
    65,
    66,
    67,
    68,
    69,
    70,
    71,
    72,
    73,
    74,
    75,
    76,
    77,
    78,
    79,
    80,
    81,
    82,
    83,
    84,
    85,
    86,
    87,
    88,
    89,
    90,
    91,
    92,
    93,
    94,
    95,
    96,
    97,
    98,
    99,
    100,
    101,
    102,
    103,
    104,
    105,
    106,
    107,
    108,
    109,
    110,
    111,
    112,
    113,
    114,
    115,
    116,
    117,
    118,
    119,
    120,
    121,
    122,
    123,
    124,
    125,
    126,
    127,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    241,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    161,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    32,
    238,
    208,
    209,
    230,
    212,
    213,
    228,
    211,
    229,
    216,
    217,
    218,
    219,
    220,
    221,
    222,
    223,
    239,
    224,
    225,
    226,
    227,
    214,
    210,
    236,
    235,
    215,
    232,
    237,
    233,
    231,
    234,
    206,
    176,
    177,
    198,
    180,
    181,
    196,
    179,
    197,
    184,
    185,
    186,
    187,
    188,
    189,
    190,
    191,
    207,
    192,
    193,
    194,
    195,
    182,
    178,
    204,
    203,
    183,
    200,
    205,
    201,
    199,
    202
  ]
  const _cyrMac = [
    0,
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20,
    21,
    22,
    23,
    24,
    25,
    26,
    27,
    28,
    29,
    30,
    31,
    32,
    33,
    34,
    35,
    36,
    37,
    38,
    39,
    40,
    41,
    42,
    43,
    44,
    45,
    46,
    47,
    48,
    49,
    50,
    51,
    52,
    53,
    54,
    55,
    56,
    57,
    58,
    59,
    60,
    61,
    62,
    63,
    64,
    65,
    66,
    67,
    68,
    69,
    70,
    71,
    72,
    73,
    74,
    75,
    76,
    77,
    78,
    79,
    80,
    81,
    82,
    83,
    84,
    85,
    86,
    87,
    88,
    89,
    90,
    91,
    92,
    93,
    94,
    95,
    96,
    97,
    98,
    99,
    100,
    101,
    102,
    103,
    104,
    105,
    106,
    107,
    108,
    109,
    110,
    111,
    112,
    113,
    114,
    115,
    116,
    117,
    118,
    119,
    120,
    121,
    122,
    123,
    124,
    125,
    126,
    127,
    225,
    226,
    247,
    231,
    228,
    229,
    246,
    250,
    233,
    234,
    235,
    236,
    237,
    238,
    239,
    240,
    242,
    243,
    244,
    245,
    230,
    232,
    227,
    254,
    251,
    253,
    255,
    249,
    248,
    252,
    224,
    241,
    160,
    161,
    162,
    163,
    164,
    165,
    166,
    167,
    168,
    169,
    170,
    171,
    172,
    173,
    174,
    175,
    176,
    177,
    178,
    179,
    180,
    181,
    182,
    183,
    184,
    185,
    186,
    187,
    188,
    189,
    190,
    191,
    128,
    129,
    130,
    131,
    132,
    133,
    134,
    135,
    136,
    137,
    138,
    139,
    140,
    141,
    142,
    143,
    144,
    145,
    146,
    147,
    148,
    149,
    150,
    151,
    152,
    153,
    154,
    155,
    156,
    179,
    163,
    209,
    193,
    194,
    215,
    199,
    196,
    197,
    214,
    218,
    201,
    202,
    203,
    204,
    205,
    206,
    207,
    208,
    210,
    211,
    212,
    213,
    198,
    200,
    195,
    222,
    219,
    221,
    223,
    217,
    216,
    220,
    192,

    255,
    0,
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20,
    21,
    22,
    23,
    24,
    25,
    26,
    27,
    28,
    29,
    30,
    31,
    32,
    33,
    34,
    35,
    36,
    37,
    38,
    39,
    40,
    41,
    42,
    43,
    44,
    45,
    46,
    47,
    48,
    49,
    50,
    51,
    52,
    53,
    54,

    55,
    56,
    57,
    58,
    59,
    60,
    61,
    62,
    63,
    64,
    65,
    66,
    67,
    68,
    69,
    70,
    71,
    72,
    73,
    74,
    75,
    76,
    77,
    78,
    79,
    80,
    81,
    82,
    83,
    84,
    85,
    86,
    87,
    88,
    89,
    90,
    91,
    92,
    93,
    94,
    95,
    96,
    97,
    98,
    99,
    100,
    101,
    102,
    103,
    104,
    105,
    106,
    107,
    108,
    109,
    110,
    111,
    112,
    113,
    114,
    115,
    116,
    117,
    118,
    119,
    120,
    121,
    122,
    123,
    124,
    125,
    126,
    127,
    192,
    193,
    194,
    195,
    196,
    197,
    198,
    199,
    200,
    201,
    202,
    203,
    204,
    205,
    206,
    207,
    208,
    209,
    210,
    211,
    212,
    213,
    214,
    215,
    216,
    217,
    218,
    219,
    220,
    221,
    222,
    223,
    160,
    161,
    162,
    222,
    164,
    165,
    166,
    167,
    168,
    169,
    170,
    171,
    172,
    173,
    174,
    175,
    176,
    177,
    178,
    221,
    180,
    181,
    182,
    183,
    184,
    185,
    186,
    187,
    188,
    189,
    190,
    191,
    254,
    224,
    225,
    246,
    228,
    229,
    244,
    227,
    245,
    232,
    233,
    234,
    235,
    236,
    237,
    238,
    239,
    223,
    240,
    241,

    242,
    243,
    230,
    226,
    252,
    251,
    231,
    248,
    253,
    249,
    247,
    250,
    158,
    128,
    129,
    150,
    132,
    133,
    148,
    131,
    149,
    136,
    137,
    138,
    139,
    140,
    141,
    142,
    143,
    159,
    144,
    145,
    146,
    147,
    134,
    130,
    156,
    155,
    135,
    152,
    157,
    153,
    151,
    154
  ]

  let fromTable = null
  let toTable = null
  let tmp
  let i = 0
  let retStr = ''

  switch (from.toUpperCase()) {
    case 'W':
      fromTable = _cyrWin1251
      break
    case 'A':
    case 'D':
      fromTable = _cyrCp866
      break
    case 'I':
      fromTable = _cyrIso88595
      break
    case 'M':
      fromTable = _cyrMac
      break
    case 'K':
      break
    default:
      // Can we throw a warning instead? That would be more in line with PHP
      throw new Error('Unknown source charset: ' + fromTable)
  }

  switch (to.toUpperCase()) {
    case 'W':
      toTable = _cyrWin1251
      break
    case 'A':
    case 'D':
      toTable = _cyrCp866
      break
    case 'I':
      toTable = _cyrIso88595
      break
    case 'M':
      toTable = _cyrMac
      break
    case 'K':
      break
    default:
      // Can we throw a warning instead? That would be more in line with PHP
      throw new Error('Unknown destination charset: ' + toTable)
  }

  if (!str) {
    return str
  }

  for (i = 0; i < str.length; i++) {
    tmp = (fromTable === null)
      ? str.charAt(i)
      : String.fromCharCode(fromTable[str.charAt(i).charCodeAt(0)])

    retStr += (toTable === null)
      ? tmp
      : String.fromCharCode(toTable[tmp.charCodeAt(0) + 256])
  }

  return retStr
}
